﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using BookingSystem.Entities;
using BookingSystem.Services;
using DayPilot.Web.Ui.Enums;
using DayPilot.Web.Ui.Events;
using FluentValidation;

namespace OSDK.Bokning
{
    public partial class Overview : Page
    {
        private int _year;

        protected void Page_Load(object sender, EventArgs e)
        {
            BookingClose.Attributes.Add("OnClick", "window.close();");
            ErrorButtonClose.Attributes.Add("OnClick", "window.close();");

            AddSomeTestData();
            ConfigureDayPilot();
            FillResources();

            if (!IsPostBack)
            {
                LoadYears();
                LoadWeeks();
                LoadBookings(DateTime.Today.Year, WeekHelper.GetWeekNumberOfDate(DateTime.Today));
            }
        }

        private void LoadYears()
        {
            _year = DateTime.Today.Year;

            const int numberOfYearsToAdd = 3;

            for (int i = 0; i < numberOfYearsToAdd; i++)
            {
                ddlYear.Items.Add((_year + i).ToString());
            }
        }

        private void LoadWeeks()
        {
            int weeksInYear = WeekHelper.WeeksInYear(_year);

            for (int i = 1; i < weeksInYear; i++)
            {
                ddlWeeks.Items.Add(new ListItem(i.ToString()));
            }

            int todaysWeekNumber = WeekHelper.GetWeekNumberOfDate(DateTime.Today);

            ddlWeeks.SelectedValue = todaysWeekNumber.ToString();
        }

        private void LoadBookings(int year, int weekNumber)
        {
            BookingNumber.Text = null;
            DateTime bookingDate = WeekHelper.GetDateFromWeek(year,
                                                              weekNumber);


            IList<BookingSystem.Entities.Booking> bookings = new BookingService().GetAllBookingsNotArchived();
            DayPilotScheduler1.StartDate = bookingDate;
            DayPilotScheduler1.DataSource = bookings;
            DayPilotScheduler1.DataBind();
        }

        private void ConfigureDayPilot()
        {
            DayPilotScheduler1.DataValueField = "Id";
            DayPilotScheduler1.DataStartField = "StartDate";
            DayPilotScheduler1.DataEndField = "EndDate";
            DayPilotScheduler1.DataResourceField = "Resource";
            DayPilotScheduler1.DataTextField = "Guest";
            DayPilotScheduler1.CellDuration = 1440/2;
            DayPilotScheduler1.StartDate = GetCurrentWeekMondayDate(DateTime.Today);
            DayPilotScheduler1.Days = Convert.ToInt32("7");
            DayPilotScheduler1.TimeFormat = TimeFormat.Clock24Hours;
            DayPilotScheduler1.CellGroupBy = GroupByEnum.Day;
            DayPilotScheduler1.BeforeTimeHeaderRender += DayPilotScheduler1_BeforeTimeHeaderRender;
            DayPilotScheduler1.EventClick += DayPilotScheduler1_EventClick;
            DayPilotScheduler1.TimeRangeSelected += DayPilotScheduler1_TimeRangeSelected;
            
        }

        private void DayPilotScheduler1_BeforeTimeHeaderRender(object sender, BeforeTimeHeaderRenderEventArgs e)
        {
            if (e.IsColGroup)
            {
                e.InnerHTML = e.Start.ToString("dddd, MMMM dd yyyy", DateTimeFormatInfo.CurrentInfo);
                // sets the group header
            }
            else
            {
                switch (e.Start.Hour)
                {
                        // sets the column header
                    case 0:
                        e.InnerHTML = "Förmiddag";
                        break;
                    case 12:
                        e.InnerHTML = "Eftermiddag";
                        break;
                }
            }
        }

        private DateTime GetCurrentWeekMondayDate(DateTime dateTime)
        {
            DayOfWeek dayInWeek = dateTime.DayOfWeek;

            int offset = 0;
            switch (dayInWeek)
            {
                case DayOfWeek.Monday:
                    offset = 0;
                    break;
                case DayOfWeek.Tuesday:
                    offset = -1;
                    break;
                case DayOfWeek.Wednesday:
                    offset = -2;
                    break;
                case DayOfWeek.Thursday:
                    offset = -3;
                    break;
                case DayOfWeek.Friday:
                    offset = -4;
                    break;
                case DayOfWeek.Saturday:
                    offset = -5;
                    break;
                case DayOfWeek.Sunday:
                    offset = -6;
                    break;
            }

            return dateTime.AddDays(offset);
        }

        private void AddSomeTestData()
        {
            var guestService = new GuestService();

            IList<BookingSystem.Entities.Guest> guests = guestService.GetByFirstName("Johan");
            if (guests.Count > 0)
            {
                return;
            }

            var guest = new BookingSystem.Entities.Guest
                            {
                                FirstName = "Johan",
                                LastName = "Spännare",
                                Address = "Anders Petters Väg 5",
                                Postalcode = "702 21",
                                City = "Örebro",
                                Birthday = DateTime.Parse("1979-04-16"),
                                Email = "johan.spannare@gmail.com",
                                Member = true,
                                Phonenumber = "0703071207"
                            };

            guestService.Save(guest);

            guest = new BookingSystem.Entities.Guest
                        {
                            FirstName = "Hanna",
                            LastName = "Spännare",
                            Address = "Anders Petters Väg 5",
                            Postalcode = "702 21",
                            City = "Örebro",
                            Birthday = DateTime.Parse("1979-02-20"),
                            Email = "hanna.spannare@gmail.com",
                            Member = true,
                            Phonenumber = "0730454627"
                        };

            guestService.Save(guest);

            guest = new BookingSystem.Entities.Guest
                        {
                            FirstName = "Patrik",
                            LastName = "Edström",
                            Address = "Patriks Väg 5",
                            Postalcode = "701 66",
                            City = "Örebro",
                            Birthday = DateTime.Parse("1983-01-12"),
                            Email = "patrik.edstrom@gmail.com",
                            Member = true,
                            Phonenumber = "0701234567"
                        };

            guestService.Save(guest);


            var roomService = new ResourceService();
            for (int i = 1; i < 11; i++)
            {
                roomService.Save(new Resource
                                     {
                                         Description = string.Format("Rum {0}, Säng A", i),
                                         Name = string.Format("Rum {0}, Säng A", i)
                                     });
                roomService.Save(new Resource
                                     {
                                         Description = string.Format("Rum {0}, Säng B", i),
                                         Name = string.Format("Rum {0}, Säng B", i)
                                     });
                roomService.Save(new Resource
                                     {
                                         Description = string.Format("Rum {0}, Säng C", i),
                                         Name = string.Format("Rum {0}, Säng C", i)
                                     });
            }


            var bookingService = new BookingService();
            var bed = new BookingSystem.Entities.Booking
                          {
                              Resource = new Resource(1),
                              StartDate = DateTime.Today.AddDays(-5),
                              EndDate = DateTime.Today.AddDays(+5),
                              Guest = new BookingSystem.Entities.Guest(1)
                          };
            bookingService.Save(bed);

            bed = new BookingSystem.Entities.Booking
                      {
                          Resource = new Resource(2),
                          StartDate = DateTime.Today.AddDays(-5),
                          EndDate = DateTime.Today.AddDays(+5),
                          Guest = new BookingSystem.Entities.Guest(2)
                      };

            bookingService.Save(bed);

            bed = new BookingSystem.Entities.Booking
                      {
                          Resource = new Resource(3),
                          StartDate = DateTime.Today.AddDays(-5),
                          EndDate = DateTime.Today.AddDays(+5),
                          Guest = new BookingSystem.Entities.Guest(3)
                      };
            bookingService.Save(bed);
        }

        private void FillResources()
        {
            var roomService = new ResourceService();
            IList<Resource> resources = roomService.GetAll();

            foreach (Resource resource in resources)
            {
                DayPilotScheduler1.Resources.Add(resource.ToString(), resource.ToString());
            }
        }

        protected void DdlWeeksOnSelectedIndexChanged(object sender, EventArgs e)
        {
            LoadBookings(Convert.ToInt32(ddlYear.SelectedValue), Convert.ToInt32(ddlWeeks.SelectedValue));
        }

        protected void DdlYearOnSelectedIndexChanged(object sender, EventArgs e)
        {
            LoadBookings(Convert.ToInt32(ddlYear.SelectedValue), Convert.ToInt32(ddlWeeks.SelectedValue));
        }

        protected void DayPilotScheduler1_EventClick(object sender, EventClickEventArgs e)
        {
            FillBookingPanel(e.ResourceId, e.Start, e.End, e.Value);
            ClientScript.RegisterStartupScript(GetType(), "key", "launchModalEdit();", true);
        }

        private void FillBookingPanel(string resourceId, DateTime start, DateTime end, string bookingNumber)
        {
            LoadGuests();

            BookingDelete.Visible = false;

            BookingSystem.Entities.Booking booking;

            if (bookingNumber != null)
            {
                BookingNumber.Text = bookingNumber;
                BookingDelete.Visible = true;
                
                booking = new BookingService().Get(Convert.ToInt32(bookingNumber));
                BookingDropDownListGuests.SelectedValue = booking.Guest.Id.ToString();
            }

            BookingStartDate.Text = start.ToString();
            BookingEndDate.Text = end.ToString();
            BookingResource.Text = resourceId;

        }

        private void DayPilotScheduler1_TimeRangeSelected(object sender, TimeRangeSelectedEventArgs e)
        {
            FillBookingPanel(e.Resource, e.Start, e.End, null);
            ClientScript.RegisterStartupScript(GetType(), "key", "launchModalEdit();", true);
        }

        private void LoadGuests()
        {
            var guestService = new GuestService();

            IList<BookingSystem.Entities.Guest> guests = guestService.GetAll();

            BookingDropDownListGuests.Items.Clear();

            foreach (BookingSystem.Entities.Guest guest in guests)
            {
                BookingDropDownListGuests.Items.Add(new ListItem(guest.Fullname(), guest.Id.ToString()));
            }
        }

        protected void BookingSave_Click(object sender, ImageClickEventArgs e)
        {
            SaveBooking(false);
        }

        private void SaveBooking(bool archive)
        {
            BookingSystem.Entities.Booking booking;

            Resource resource = new ResourceService().GetByName(BookingResource.Text);

            BookingSystem.Entities.Guest guest =
                new GuestService().Get(Convert.ToInt32(BookingDropDownListGuests.SelectedValue));


            var bookingService = new BookingService();

            if (BookingNumber.Text != string.Empty)
            {
                booking = bookingService.Get(Convert.ToInt32(BookingNumber.Text));

                if (archive)
                {
                    booking.Archived = true;
                }
            }
            else
            {
                booking = new BookingSystem.Entities.Booking();
            }

            booking.StartDate = DateTime.Parse(BookingStartDate.Text);
            booking.EndDate = DateTime.Parse(BookingEndDate.Text);
            booking.Guest = guest;
            booking.Resource = resource;

            try
            {
                bookingService.Save(booking);
            }
            catch (ValidationException e)
            {
                var message = new StringBuilder();

                foreach (var error  in e.Errors)
                {
                    message.AppendLine(error.ErrorMessage);
                }

                ErrorMessage.Text = message.ToString();
                ClientScript.RegisterStartupScript(GetType(), "key", "launchModalError();", true);
            }
            

            LoadBookings(Convert.ToInt32(ddlYear.SelectedValue), Convert.ToInt32(ddlWeeks.SelectedValue));
        }

        protected void BookingDelete_Click(object sender, EventArgs e)
        {
            SaveBooking(true);
        }
    }
}